package com.suray.basic.wcs.plc.pojo.oper.single;

import com.suray.basic.wcs.plc.config.resolver.PlcAnnotation;
import com.suray.basic.wcs.plc.core.PlcOffset;
import com.suray.basic.wcs.plc.enums.Location;
import com.suray.basic.wcs.plc.enums.PlcDeviceType;
import com.suray.basic.wcs.plc.pojo.DeviceBase;
import com.suray.basic.wcs.plc.utils.FoldingMachineManualAct;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.WcsFuncUtil;

import java.io.IOException;

/**
 * 拆碟盘机
 */
public class FoldingOper extends DeviceBase implements DeviceInterface {
    //设备类型 写
    private static final int DEVICETYPE = 0;
    //位移量 写
    private static final int MOVEMENT = 1;
    //升降自动速度 写
    private static final int LIFT_AUTO_SPEED = 2;
    //升降自动加速时间 写
    private static final int LIFT_AUTO_ACC = 3;
    //升降自动减速时间 写
    private static final int LIFT_AUTO_DEC = 4;
    //升降手动速度 写
    private static final int LIFT_MANUAL_SPEED = 5;
    //升降手动加速时间 写
    private static final int LIFT_MANUAL_ACC = 6;
    //升降手动减速时间 写
    private static final int LIFT_MANUAL_DEC = 7;
    /*******读********/
    private static final PlcOffset DEVICE_TYPE = new PlcOffset(8, null);
    //任务号
    private static final PlcOffset TASK_NO = new PlcOffset(9, null);
    //起点设备编号
    private static final PlcOffset TASK_START_LOCATION = new PlcOffset(10, null);
    //终点设备编号
    private static final PlcOffset TASK_END_LOCATION = new PlcOffset(11, null);
    //托盘数量
    private static final PlcOffset PALLET_NUM = new PlcOffset(12, null);
    //故障码
    private static final PlcOffset ERROR_INFO = new PlcOffset(13, null);
    //校准位
    private static final PlcOffset CHECK_NO = new PlcOffset(14, null);

    private static final PlcOffset STOP_STATE = new PlcOffset(15, 0);
    private static final PlcOffset MODE_MANUAL = new PlcOffset(15, 1);
    private static final PlcOffset CONTROL_MODE = new PlcOffset(15, 2);
    private static final PlcOffset DEVICE_RUN = new PlcOffset(15, 3);
    private static final PlcOffset ERROR_ALARM = new PlcOffset(15, 4);
    private static final PlcOffset UPPER_PLACE = new PlcOffset(15, 5);
    private static final PlcOffset MIDDLE_PLACE = new PlcOffset(15, 6);
    private static final PlcOffset DOWN_PLACE = new PlcOffset(15, 7);
    private static final PlcOffset PALLET_HEIGHT = new PlcOffset(15, 8);
    private static final PlcOffset REACH_PLACE = new PlcOffset(15, 9);
    private static final PlcOffset SHRINK_PLACE = new PlcOffset(15, 10);
    private static final PlcOffset PALLET_1 = new PlcOffset(15, 11);
    private static final PlcOffset PALLET_2 = new PlcOffset(15, 12);
    private static final PlcOffset PROXIMITY_SIGNAL = new PlcOffset(15, 13);

    //任务号
    private static final int TASK_NUM = 18;
    //起点 写
    private static final int START_TASK = 19;
    //终点
    private static final int END_TASK = 20;
    //清除任务信息
    private static final int CLEAR_TASK = 21;
    //拆叠盘机动作
    private static final int ACTION_TASK = 22;
    //故障清除
    private static final PlcOffset CLEAR_ERROR = new PlcOffset(23, 0);
    //手动上升
    private static final PlcOffset MANUAL_UP = new PlcOffset(23, 1);
    //手动下降
    private static final PlcOffset MANUAL_DOWN = new PlcOffset(23, 2);
    //推杆伸出
    private static final PlcOffset MANUAL_REACH = new PlcOffset(23, 3);
    //推杆缩回
    private static final PlcOffset MANUAL_SHRINK = new PlcOffset(23, 4);

    public FoldingOper(PlcDeviceType plcDeviceType, int startNo, String deviceName, int deviceNo, Coord coord, Location location, Coord lockLocation, long deviceId, Integer gridzMax, Integer gridzRelative, int plcId) {
        super(plcDeviceType, startNo, deviceName, deviceNo, coord, location, lockLocation, deviceId, gridzMax, gridzRelative, plcId);
    }


    public Integer getCheckNo() {
        return readPlc(CHECK_NO);
    }
    public Integer getPalletNum() {
        return readPlc(PALLET_NUM);
    }
    public Integer getDeviceType() {
        return readPlc(DEVICE_TYPE);
    }
    @PlcAnnotation(value = "设置设备类型")
    public void setDeviceType()throws IOException {
        oper("设置设备类型", this.getClass(), DEVICETYPE,3,11);
    }

    public Integer getLiftAutoSpeed() {
        return readPlc(new PlcOffset(LIFT_AUTO_SPEED, null));
    }

    /**
     * 设置升降自动速度
     * @return
     */
    @PlcAnnotation(value = "设置升降自动速度")
    public void setLiftAutoSpeed(int speed) throws IOException {
        LoggerUtil.info("升降自动速度:" + speed, this.getClass());
        oper("设置升降自动速度", this.getClass(), LIFT_AUTO_SPEED, 10, speed);
    }

    public Integer getLiftAutoAcc() {
        return readPlc(new PlcOffset(LIFT_AUTO_ACC, null));
    }

    /**
     * 设置升降自动加速时间
     * @return
     */
    @PlcAnnotation(value = "设置升降自动加速时间")
    public void setLiftAutoAcc(int time) throws IOException {
        LoggerUtil.info("升降自动加速时间:" + time, this.getClass());
        oper("设置升降自动加速时间", this.getClass(), LIFT_AUTO_ACC, 10, time);
    }

    public Integer getLiftAutoDec() {
        return readPlc(new PlcOffset(LIFT_AUTO_DEC, null));
    }

    /**
     * 设置升降自动减速时间
     * @return
     */
    @PlcAnnotation(value = "设置升降自动减速时间")
    public void setLiftAutoDec(int time) throws IOException {
        LoggerUtil.info("升降自动减速时间:" + time, this.getClass());
        oper("设置升降自动减速时间", this.getClass(), LIFT_AUTO_DEC, 10, time);
    }

    public Integer getLiftManualSpeed() {
        return readPlc(new PlcOffset(LIFT_MANUAL_SPEED, null));
    }

    /**
     * 设置升降手动速度
     * @return
     */
    @PlcAnnotation(value = "设置升降手动速度")
    public void setLiftManualSpeed(int speed) throws IOException {
        LoggerUtil.info("升降手动速度:" + speed, this.getClass());
        oper("设置升降手动速度", this.getClass(), LIFT_MANUAL_SPEED, 10, speed);
    }

    public Integer getLiftManualAcc() {
        return readPlc(new PlcOffset(LIFT_MANUAL_ACC, null));
    }

    /**
     * 设置升降手动加速时间
     * @return
     */
    @PlcAnnotation(value = "设置升降手动加速时间")
    public void setLiftManualAcc(int time) throws IOException {
        LoggerUtil.info("升降手动加速时间:" + time, this.getClass());
        oper("设置升降手动加速时间", this.getClass(), LIFT_MANUAL_ACC, 10, time);
    }

    public Integer getLiftManualDec() {
        return readPlc(new PlcOffset(LIFT_MANUAL_DEC, null));
    }

    /**
     * 设置升降手动减速时间
     * @return
     */
    @PlcAnnotation(value = "设置升降手动减速时间")
    public void setLiftManualDec(int time) throws IOException {
        LoggerUtil.info("升降手动减速时间:" + time, this.getClass());
        oper("设置升降手动减速时间", this.getClass(), LIFT_MANUAL_DEC, 10, time);
    }

    public Integer getTaskEndTaskNo() {
        return readPlc(TASK_END_LOCATION);
    }

    public Integer getTaskEndStartNo() {
        return readPlc(TASK_START_LOCATION);
    }

    public Integer getTaskEndEndNo() {
        return readPlc(TASK_END_LOCATION);
    }

    /**
     * 拆叠盘机动作
     * @return
     */
    @PlcAnnotation(value = "拆叠盘机动作")
    public void setActionTask(int actionTask) throws IOException {
        LoggerUtil.info("拆叠盘机动作:" + actionTask, this.getClass());
        oper("拆叠盘机动作", this.getClass(), ACTION_TASK, 10, actionTask);
    }
    /**
     * 清除故障
     * @return
     */
    @PlcAnnotation(value = "清除故障")
    public void setClearError() throws IOException {
        LoggerUtil.info("清除故障:" , this.getClass());
        oper("清除故障", this.getClass(), CLEAR_ERROR.getAddressOffset(), 10, 1 << CLEAR_ERROR.getBitOffset());
    }

    /**
     * 手动上升
     * @return
     */
    @PlcAnnotation(value = "手动上升")
    public void manualUp() throws IOException {
        LoggerUtil.info("手动上升:" , this.getClass());
        oper("手动上升", this.getClass(), MANUAL_UP.getAddressOffset(), 10, FoldingMachineManualAct.MANUAL_UP);
    }
    /**
     * 手动下降
     * @return
     */
    @PlcAnnotation(value = "手动下降")
    public void manualDown() throws IOException {
        LoggerUtil.info("手动下降:" , this.getClass());
        oper("手动下降", this.getClass(), MANUAL_DOWN.getAddressOffset(), 10, FoldingMachineManualAct.MANUAL_DOWN);
    }
    /**
     * 推杆伸出
     * @return
     */
    @PlcAnnotation(value = "推杆伸出")
    public void manualPush() throws IOException {
        LoggerUtil.info("推杆伸出:" , this.getClass());
        oper("推杆伸出", this.getClass(), MANUAL_REACH.getAddressOffset(), 10, FoldingMachineManualAct.MANUAL_PUSH);
    }
    /**
     * 推杆缩回
     * @return
     */
    @PlcAnnotation(value = "推杆缩回")
    public void manualRetract() throws IOException {
        LoggerUtil.info("推杆缩回:" , this.getClass());
        oper("推杆缩回", this.getClass(), MANUAL_SHRINK.getAddressOffset(), 10, FoldingMachineManualAct.MANUAL_RETRACT);
    }

    public boolean isStopSingal() {return readPlc(STOP_STATE)==1;}
    public boolean getManualMode() {return readPlc(MODE_MANUAL)==1;}
    public boolean isUpperInPlace() {return readPlc(UPPER_PLACE)==1;}
    public boolean gisMiddleInPlace() {return readPlc(MIDDLE_PLACE)==1;}
    public boolean isDownInPlace() {return readPlc(DOWN_PLACE)==1;}
    public boolean isPalletHeight() {return readPlc(PALLET_HEIGHT)==1;}
    public boolean isReachInPlace() {return readPlc(REACH_PLACE)==1;}
    public boolean isShrinkInPlace() {return readPlc(SHRINK_PLACE)==1;}
    public boolean isPallet1() {return readPlc(PALLET_1)==1;}
    public boolean isPallet2() {return readPlc(PALLET_2)==1;}
    public boolean isProximity() {return readPlc(PROXIMITY_SIGNAL)==1;}

    @Override
    public boolean hasCargo() {
        return false;
    }

    @Override
    public boolean inCargoSignal() {
        return false;
    }

    @Override
    public boolean outCargoSignal() {
        return false;
    }

    @Override
    public boolean permitRun() {
        return false;
    }

    @Override
    public boolean canControl() {

        if(readPlc(CONTROL_MODE)==1){
            return true;
        }
        return false;
    }

    @Override
    public boolean isRunning() {
        return readPlc(DEVICE_RUN)==1;
    }

    @Override
    public boolean isError() {
        return readPlc(ERROR_ALARM)==1;
    }

    @Override
    public Integer errorCode() {
        return readPlc(ERROR_INFO);
    }

    @Override
    public Integer getTaskNo() {
        return readPlc(TASK_NO);
    }

    @Override
    public Integer getTaskStartLocation() {
        return readPlc(TASK_START_LOCATION);
    }

    @Override
    public Integer getTaskEndLocation() {
        return readPlc(TASK_END_LOCATION);
    }

    @Override
    @PlcAnnotation("发送任务")
    public void sendConveryTask(int taskNo, int startDeviceNo, int endDeviceNo) throws IOException {
        String des = getDeviceStatus();
        while (getTaskNo() != 0) {
            setDeviceStatus("任务号不为0，不能下发任务：" + taskNo);
            WcsFuncUtil.delay(1000);
        }
        setDeviceStatus(des);

        int[] data = new int[3];
        data[0] = taskNo;
        data[1] = startDeviceNo;
        data[2] = endDeviceNo;
        LoggerUtil.info("发送任务，任务编号：" + taskNo + ", 起点:" + startDeviceNo + ", 终点:" + endDeviceNo,
                this.getClass());
        oper("发送任务", this.getClass(), TASK_NUM, 10, data);
    }

    @Override
    @PlcAnnotation("清除任务编号")
    public void clearTaskNo() throws IOException {
        LoggerUtil.info("清除任务编号，设备：" + getDeviceName(), this.getClass());
        oper("清除任务编号", this.getClass(), CLEAR_TASK, 10, 1);
    }
}
